/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package analiseSintatica.Regras.Funcao;

import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSemantica.ErroSemantico;
import analiseSemantica.Tipos.TipoSemantico;
import analiseSemantica.Tipos.TiposSemanticos;
import analiseSemantica.estruturadedados.Escopo;
import analiseSintatica.AnalisadorSintatico;
import analiseSintatica.ErroSintaticoException;
import analiseSintatica.Regras.Blocos.RegraCorpoFuncao;
import analiseSintatica.Regras.DeclaracoesIniciais.RegraPrototipo;
import analiseSintatica.Regras.Regra;
import java.util.LinkedList;

/**
 *
 * @author Dede do Bem
 * 
 * <funcao> ::= <prototipo> <corpo_funcao>
 */
public class RegraFuncao extends Regra{

    protected static Regra instancia;

    protected String estrutura = "<prototipo> <corpo_funcao>";
    RegraPrototipo prototipo;
    RegraCorpoFuncao corpoFuncao;


    /**
     * Construtor privado necessario ao singleton
     */
    private RegraFuncao() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraFuncao getInstance() {
        if (instancia == null) {
            instancia = new RegraFuncao();
        }
        return (RegraFuncao) instancia;
    }
    

    @Override
    public TiposSemanticos analisar(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {

    	AnalisadorSintatico.escopoatual = new Escopo(AnalisadorSintatico.escopoatual);
    	TiposSemanticos tiposprototipo = RegraPrototipo.getInstance().analisar(listaTokens);
    	TipoSemantico tipoprototipo = null;
    	String tipoprot = null;
    	if(tiposprototipo != null){
    		tipoprototipo = tiposprototipo.removeTipos();
            tipoprot = (String)tipoprototipo.getTipo();
    	}
        
        TiposSemanticos tiposfuncao = RegraCorpoFuncao.getInstance().analisar(listaTokens);
        TipoSemantico tipofuncao;
        if(tiposprototipo != null){
	        if(!tipoprot.equals("void")){
	        	if(tiposfuncao.size() == 0){
	        		AnalisadorSintatico.errosemanticos.add(new ErroSemantico("A Funcao nao e void e deve ter retorno", tipoprototipo.getLinha()));
	        	}
	        }
	        while (tiposfuncao.size() != 0){
	        	tipofuncao = tiposfuncao.removeTipos();
	        	String retorno = (String)tipofuncao.getTipo();
	        	if (!tipoprot.equals(retorno))
	        		AnalisadorSintatico.errosemanticos.add(new ErroSemantico("O retorno "+retorno+" nao confere com o tipo da funcao "+tipoprot, tipofuncao.getLinha()));
	        }
	        
        }
        AnalisadorSintatico.escopoatual = AnalisadorSintatico.escopoatual.getParent();
        return null;
    }
    
  

    @Override
    protected void setPrimeiro() {
        this.primeiro = RegraPrototipo.getInstance().getPrimeiro();
    }

    

}
